/**
 * 
 */
package org.dragonfire.dasm;

import java.util.ArrayList;
import java.util.Stack;

import org.dragonfire.dasm.instr.Instruction;

/**
 * @author dandroid
 * @date Dec 1, 2006
 */
public class Listing {

	/**
	 * Creates a listing with the specified size, in bytes.
	 * 
	 * @param size
	 *            The size of the data that this listing will hold.
	 */
	public Listing(int size) {
		mCode = new byte[size];
	}

	public Listing(int size, Command c) {
		this(size);
		setCommand(c);
	}

	public Listing(byte[] data) {
		mCode = data;
	}

	public Listing(byte[] data, Command c) {
		this(data);
		setCommand(c);
	}

	private int pc = -1;
	private byte[] mCode = null;
	private Instruction ins = null;
	private Command cmd = null;
	private int lineNum = -1;
	private int absLine = -1;
	private String fileName = null;
	private boolean visible = true;
	private boolean lsFirst = true;
	private String[] moduleStack = null;

	public void setModuleStack(Stack<String> modules) {
		setModuleStack(modules.toArray(new String[modules.size()]));
	}

	public void setModuleStack(String[] modules) {
		moduleStack = modules;
	}

	public String[] getModuleStack() {
		return moduleStack;
	}

	public boolean isVisible() {
		return visible;
	}

	public void setLSFirst(boolean bool) {
		lsFirst = bool;
	}

	public boolean isLSFirst() {
		return lsFirst;
	}

	public void setVisible(boolean visible) {
		this.visible = visible;
	}

	public int getAbsLine() {
		return absLine;
	}

	public void setAbsLine(int absLine) {
		this.absLine = absLine;
	}

	public Command getCommand() {
		return cmd;
	}

	public void setCommand(Command command) {
		cmd = command;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public Instruction getInstruction() {
		return ins;
	}

	public void setInstruction(Instruction ins) {
		this.ins = ins;
	}

	public int getLineNum() {
		return lineNum;
	}

	public void setLineNum(int lineNum) {
		this.lineNum = lineNum;
	}

	public byte[] getMCode() {
		return mCode;
	}

	public int getSize() {
		return mCode.length;
	}

	public void setMCode(byte[] code) {
		if (getSize() != code.length)
			throw new CompileException("ERROR_AMORPHOUS_COMMAND");
		mCode = code;
	}

	public void setMCode(ArrayList<Byte> code) {
		byte[] data = new byte[code.size()];
		for (int i = 0; i < data.length; i++) {
			data[i] = code.get(i);
		}
		setMCode(data);
	}

	public String getModule() {
		String[] modules = getModuleStack();
		if (modules.length == 0)
			return "";
		return modules[modules.length - 1];
	}

	public int getPc() {
		return pc;
	}

	public void setPc(int pc) {
		this.pc = pc;
	}

	public String toString() {
		String str = String.format("%20s:%04d:%08X:", getFileName(), getLineNum(), getPc());
		String tmp = "";
		for (int i = 0; i < getMCode().length; i++) {
			tmp += String.format(" %02X", getMCode()[i]);
			if (i % 4 == 3) {
				str += String.format("%-11s", tmp.substring(1));
				tmp = "";
				if (i < getMCode().length - 1) {
					str += "\n" + String.format("%35s", "");
				}
			}
		}
		if (getMCode().length % 4 != 0)
			str += String.format("%-11s", tmp.substring(1));
		if (getMCode().length == 0)
			str += String.format("%-11s", "");
		str += ": " + getCommand();
		return str;
	}
}
